﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Lrd.Permissions.CodeGenerator;
using Lrd.Permissions.Common;
using Lrd.Permissions.Core;
using Lrd.Permissions.Repository;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.IdentityModel.Tokens;
using Swashbuckle.AspNetCore.Swagger;

namespace Lrd.Permissions.Demo.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            ModulePackManager modulePackManager = new ModulePackManager();
            services.AddSingleton<IModulePackManager>(modulePackManager);
            modulePackManager.LoadPacks(services);
            services.AddSingleton(typeof(IEntityManager), typeof(EntityManager));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddJsonOptions(options => { options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver(); })
           .ConfigureApiBehaviorOptions(options =>
           {
               options.SuppressConsumesConstraintForFormFileParameters = true;
               options.SuppressInferBindingSourcesForParameters = true;
               options.SuppressModelStateInvalidFilter = true;
               options.SuppressMapClientErrors = true;


           });
   
            string entryAssemblyName = Assembly.GetExecutingAssembly().GetName().Name;
            //b => b.MigrationsAssembly(entryAssemblyName)
            //services.AddDbContext<DefaultDbContext>((provider, options) => options.UseSqlServer("Data Source=.;Initial Catalog=Lrd.Permissions2;User ID=sa;Password=123;", b =>
            //{

            //    b.UseRowNumberForPaging(true);
            //    b.MigrationsAssembly(entryAssemblyName);
            //})
            //        );

            services.AddDbContext<DefaultDbContext>((provider, options) => options.UseMySql("Server=172.28.226.62;Port=33305;UserId=root;Password=123456;Database=Test;charset='utf8';Allow User Variables=True", b =>
            {

                b.MigrationsAssembly(entryAssemblyName);
            }));
            EntityManager entityManager = new EntityManager();
            entityManager.Initialize();
        
            services.AddScoped(typeof(IUnitOfWork), typeof(UnitOfWork));
            services.AddScoped(typeof(IRepository<,>), typeof(Repository<,>));


        
            services.AddScoped<IUserStore<User>, UserStore>();
            services.AddScoped<IRoleStore<Role>, RoleStore>();
            services.AddIdentity<User, Role>(options =>
            {
               
                options.SignIn.RequireConfirmedEmail = false;

                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = false;
 
                options.User.RequireUniqueEmail = false;
        
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);

                options.Password.RequireDigit = false;
                options.Password.RequireLowercase = false;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = false;
                options.Password.RequiredLength = 6;
                options.Password.RequiredUniqueChars = 1;

               
            }).AddDefaultTokenProviders();


            services.Configure<DbOptions>(o =>
            {
                o.ConnectionString = "Data Source=.;Initial Catalog=Cms.Core;User ID=sa;Password=123";
                o.DatabaseType = DatabaseType.SqlServer;

            });
            services.AddScoped<IDbServices, SqlServiceDbServices>();
            services.AddScoped<ICodeGenerator, RazorCodeGenerator>();

            var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("8619F7C3-B53C-4B85-99F0-983D351ECD82"));
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                //x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(jwt =>
            {
                jwt.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidIssuer = "lrd identity",
                    ValidAudience = "lrd identity",
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("8619F7C3-B53C-4B85-99F0-983D351ECD82")),
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero, ////允许的服务器时间偏移量
                    SaveSigninToken=true,
                    
                };

                jwt.Events = new JwtBearerEvents /*jwt自带事件*/
                {
                    OnAuthenticationFailed = context =>
                    {



                        // 如果过期，则把<是否过期>添加到，返回头信息中
                        if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        {
                            context.Response.Headers.Add("Token-Expired", "true");
                        }
                        return Task.CompletedTask;
                    },
                };
            });

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Info { Title = "Lrd.Permissions.Demo.Web", Version = "v1" });

                // TODO:一定要返回true！
                options.DocInclusionPredicate((docName, description) =>
                {
                    return true;
                });
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                options.IncludeXmlComments(Path.Combine(basePath, "Lrd.Permissions.Demo.Web.xml"), true);

                options.AddSecurityDefinition("Bearer", new ApiKeyScheme
                {
                    Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}（注意两者之间是一个空格）\"",
                    Name = "Authorization",//jwt默认的参数名称
                    In = "header",//jwt默认存放Authorization信息的位置(请求头中)
                    Type = "apiKey"
                });

                options.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
                {
                    { "Bearer", new string[] { } }
                });
            });

           
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
    
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

           var packManager = app.ApplicationServices.GetService<IModulePackManager>();
            packManager.UsePack(app.ApplicationServices);
            app.UseAuthentication();

            app.UseErrorHandling();
            app.UseMvc();

            //启用中间件服务生成Swagger作为JSON终结点
            app.UseSwagger();
            //启用中间件服务对swagger-ui，指定Swagger JSON终结点
            app.UseSwaggerUI(c =>
            {
                c.RoutePrefix = string.Empty;
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "Lrd.Permissions.Demo.Web");
   
            });
        }
    }
}
